#include"../server.hpp"

//模块功能：基于“时间轮盘”这一方案，实现对“连接”的超时处理和延时处理
// using taskfunc=std::function<void()>;
// using releasefunc=std::function<void()>;
// class timetask{
//     private:
//     uint64_t _task_id;//标识每一个任务
//     int _init_pos;//初次延时
//     int _timeout;//每个任务的超时时间
//     taskfunc _task_cb;//需要执行的任务————封装的核心
//     releasefunc _release_cb;//清除timewheel中有关timetask的信息

//     public:
//     //初始化任务
//     timetask(uint64_t id,int init_pos,int timeout,const taskfunc& cb,const releasefunc& release_cb)
//     :_task_id(id),_init_pos(init_pos),_timeout(timeout),_task_cb(cb),_release_cb(release_cb)
//     {std::cout<<"构造成功..."<<std::endl;}
//     //销毁任务——>执行任务, 当一个任务被销毁时，它要提醒timewheel，让_task_hash删除关于它的信息，这一功能同样是由一个回调函数完成的
//     ~timetask(){ _task_cb(); _release_cb(); std::cout<<"析构成功..."<<std::endl; }

//     //id外裸接口
//     uint64_t GetId(){return _task_id;} 
//     //timeout外裸接口
//     int GetTimeout(){return _timeout;}
//     //init_pos外裸接口
//     int GetInitPos(){return _init_pos;}
// };

// class timewheel{
//     using task_ptr=std::shared_ptr<timetask>;
//     using task_weak=std::weak_ptr<timetask>;
//     private:
//     int _pos;//滴答指针————走到哪里，就释放哪里的对象，即执行哪里的任务
//     int _capacity;//轮盘大小
//     std::vector<std::vector<task_ptr>> _task_wheels;//任务轮盘
//     std::unordered_map<uint64_t,task_weak> _task_hash;//优化id遍历时间轮盘的时间复杂度 O(N)————>O(logN)

//     public:
//     void RemoveTask(uint64_t id)
//     {
//         //删除前，先判断id是否存在
//         auto iter=_task_hash.find(id);
//         if(iter!=_task_hash.end())
//             _task_hash.erase(iter);
//         std::cout<<"task_weak remove from _tast_arr successfully..."<<std::endl;
//     }
//     public:
//     //初始化时间轮盘
//     timewheel():_pos(0),_capacity(60),_task_wheels(_capacity){}
//     //销毁时间轮盘
//     ~timewheel(){}
//     //添加任务
//     bool AddTask(uint64_t id,int init_pos,int timeout,const taskfunc& task)
//     {
//         //1.由于RemoveTask参数由this，所以需要bind；2.id已经被bind，故调用release_cb时无需再次传参。注意这里release_cb和RemoveTask的类型，bind后的函数参数类型！！！
//         task_ptr new_task(new timetask(id,init_pos,timeout,task,std::bind(&timewheel::RemoveTask,this,id)));//??? ————为啥用=赋值不行
        
//         _task_wheels[(_pos+init_pos)%_capacity].push_back(new_task);
//         _task_hash[id]=task_weak(new_task);
//     }
//     //延时任务————本质就是，在时间轮盘中再添加一个id相同的task_ptr指针，让其引用计数++，使得timetask延时释放，即任务延时执行
//     bool DelayTask(uint64_t id)
//     {
//         //遍历效率低下————O(N)  解决方案：用一个unordered_map存放task_ptr，遍历unordered_map，优化到O(logN)
//         // for(int i=0;i<_capacity;i++){
//         //     for(const auto& task:_task_wheels[i]){
//         //         if(task.GetId()==id){
//         //             task_ptr new_task(task);
//         //             _task_wheels[(_pos+task.GetTimeout())%_capacity].push_back(new_task);
//         //         }
//         //     }
//         // }
//         //延时前，先判断id是否存在
//         auto iter=_task_hash.find(id);
//         if(iter!=_task_hash.end())
//         {
//             task_ptr buf_task=iter->second.lock();//由weak_ptr得到shared_ptr的接口
//             _task_wheels[(_pos+buf_task->GetTimeout())%_capacity].push_back(buf_task);
//             std::cout<<"延时成功..."<<std::endl;
//         }
//         else std::cout<<"延时失败..."<<std::endl;
//     }
//     //转动时间轮盘
//     void CarryStep(){
//         _task_wheels[_pos].clear();//释放_pos位置的所有task_ptr，timetask析构，cb被动执行
//         _pos=(_pos+1)%_capacity;
//     }
// };

// void Print()
// {
//     std::cout<<"你好，我是测试函数..."<<std::endl;
// }

// int main()
// {
//     //测试
//     EventLoop eventloop;
//     TimeWheel tw(&eventloop);

//     tw.AddTaskInOneLoop(888,3,1,Print);//3秒后执行Print函数，如果有延迟指令，则延迟周期是5秒
    
//     while(1){
//         tw.DelayTaskInOneLoop(888);
//     }

//     return 0;
// }

//用类对象的生命周期+智能指针来实现任务控制
//创建类：封装需要执行的任务
using Task=std::function<void()>;
class TimeTask
{
private:
    int _id;//任务id
    int _init_pos;//初次执行时间
    int _timeout;//延迟的时间间隔
    Task _task;//需要执行的任务
    Task _release_cb;//timewheel回调函数

public:
    TimeTask(int id,int init_pos,int timeout,const Task& task,const Task& release_cb)
    :_id(id),_init_pos(init_pos),_timeout(timeout),_task(task),_release_cb(release_cb)
    {}
};

//时间轮盘，查找超时连接，并断开
//用一个指针轮询式遍历一个数组，每走到一个位置，就执行该位置上的任务
class TimeWheel
{
    using task_shared_ptr=std::shared_ptr<TimeTask>;
    using task_weak_ptr=std::weak_ptr<TimeTask>;
private:
    int _pos;//滴答指针
    int _capacity;//数组大小
    std::vector<std::vector<task_shared_ptr>> _vv;
    std::unordered_map<int,task_weak_ptr> _hash;
public:
    TimeWheel():_pos(0),_capacity(0),_vv(_capacity){}

    void AddOneTask(int id,int init_pos,int timeout,const Task& task)
    {
        task_shared_ptr new_task(new TimeTask(id,init_pos,timeout,task,std::bind(&TimeWheel::RemoveTask,this,id)));
        _vv[(_pos+init_pos)%_capacity].push_back(new_task);
        _hash[id]=task_weak_ptr(new_task);
    }

    void RemoveTask(int id)                  
    {
        auto iter=_hash.find(id);
        if(iter!=_hash.end())
        {
            _hash.erase(iter);
        }
    }

    void RunOneStep(){
        _vv[_pos].clear();
        _pos=(_pos+1)%_capacity;          
    }
};